package com.imooc.sell.service.impl;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.imooc.sell.VO.xia.CodeVO;
import com.imooc.sell.dao.AdminUserDao;
import com.imooc.sell.dto.UserInfoDTO;
import com.imooc.sell.service.AuthoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * 授权业务实现类
 */
@Service
@Slf4j
public class AuthoServiceImpl implements AuthoService {

    @Autowired
    private AdminUserDao adminDao;

    private String APPID = "wx9388cec512d7f8b7";
    private String APPSECRET = "63c03b2c1f3c8eb62a97c156f7d149cd";
    private String REDIRECT_URL = "http://bread.s1.natapp.cc/sell/autho/getcode";
    private String responseType = "code";

    private Gson gson;

    /**
     * @param scope 请求用户信息方式
     * @return 获取code的url
     */
    @Override
    public CodeVO codeGetUrl(String scope, String redirectUrl, String state) {
        CodeVO vo = new CodeVO();
        String AUTH_CODE_URL_BASE = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=%s&scope=%s&state=%s#%s";
        try {
            vo.setCodeGetUrl(String.format(AUTH_CODE_URL_BASE, APPID, redirectUrl,
                    responseType, scope, state, redirectUrl));
            vo.setMcode(1);
            vo.setMsg("成功");
        } catch (Exception e) {
            log.error("url拼接错误，请检查拼接字符");
            vo.setMcode(0);
            vo.setMsg("获取code失败");
        }
        return vo;
    }

    @Override
    public CodeVO codeGetUrl(String scope, String state) {

        return codeGetUrl(scope, REDIRECT_URL, state);
    }

    /**
     * @param code code码
     */
    public Map<String, String> getToken(String code) {
        String AUTH_TOKEN_URL_BASE = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        /* 创建返回列表*/
        Map<String, String> map = new HashMap<>();
        /* 拼接请求地址*/
        String url = String.format(AUTH_TOKEN_URL_BASE, APPID, APPSECRET, code);
        /* 声明返回值*/
        String result;
        //创建POST请求
        HttpPost httpPost = new HttpPost(url);
        try (
                //创建httpClient对象
                CloseableHttpClient httpClient = HttpClients.createDefault();
                //创建response对象,用于接收返回数据,发起请求
                CloseableHttpResponse response = httpClient.execute(httpPost)
        ) {
            //判断是否成功
            if (response.getStatusLine().getStatusCode() == 200) {
                //读返回数据
                result = EntityUtils.toString(response.getEntity(), "UTF-8");
                JsonObject jb = (JsonObject) new JsonParser().parse(result);
                //这里需要属性较少可以用JsonObject方式解析
                map.put("openid", jb.get("openid").getAsString());
                map.put("access_token", jb.get("access_token").getAsString());
                map.put("refresh_token", jb.get("refresh_token").getAsString());
            } else {
                log.error("{}请求token失败!", getClass());
            }
        } catch (Exception e) {
            log.error("{}网络连接失败", getClass());
        }
        return map;
    }

    public Map<String, Object> getUserInfo(String openid, String access_token, String refresh_token) {
        String AUTH_USER_INFO_BASE = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
        /* 初始化返回列表*/
        Map<String, Object> map = new HashMap<>();
        /* 拼接请求的url*/
        String url = String.format(AUTH_USER_INFO_BASE, access_token, openid);
        /* 声明微信server结果返回变量*/
        String result;
        //创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建POST请求
        HttpPost httpPost = new HttpPost(url);
        try {
            //创建response对象,用于接收返回数据,发起请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            //判断是否成功
            if (response.getStatusLine().getStatusCode() == 200) {
                //读返回数据
                result = EntityUtils.toString(response.getEntity(), "UTF-8");

                /*解析错误*/
                Gson gson = new Gson();
                UserInfoDTO user = gson.fromJson(result, UserInfoDTO.class);
                map.put("openid", user.getOpenid());
                map.put("headImg", user.getHeadimgurl());
                map.put("nickName", user.getNickname());
                map.put("mcode", 1);
            } else {
                log.error("请求数据错误");
                map.put("mcode", 0);
                map.put("msg", "请求失败");
            }
        } catch (Exception e) {
            log.error("网络请求失败");
            map.put("mcode", 0);
            map.put("msg", "网络异常");
        }
        return map;
    }

    public void accessCode(String url) {
        String result = getURLContent(url);
    }


    public static String getURLContent(String urlStr) {
        /** 网络的url地址 */
        URL url = null;
        /** http连接 */
        HttpURLConnection httpConn = null;
        /**//** 输入流 */
        BufferedReader in = null;
        StringBuffer sb = new StringBuffer();
        try {
            url = new URL(urlStr);
            in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
            String str = null;
            while ((str = in.readLine()) != null) {
                sb.append(str);
            }
        } catch (Exception ex) {

        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
            }
        }
        String result = sb.toString();
        return result;
    }


    /**
     * @param openid
     * @return 如果数据库中存在此用户则返回true，否则返回false
     */
    public boolean validate(String openid) {
        boolean result = false;
        try {
            result = (null != adminDao.getOne(openid));
        } catch (Exception e) {
            log.info("{}未查询到用户");
        }
        return result;
    }
}
